# -*- coding: utf-8 -*-
# created on 2016/12/13

from sympy import S, latex, Union, EmptySet, FiniteSet, solveset, oo
from mathsolver.functions.base import BaseSymbolValue, BaseIneqs, BaseVariables, BaseFunction, BaseIneq
from mathsolver.functions.budengshi.jiebudengshi import JieBuDengShi
from mathsolver.functions.hanshu.helper import check_belong, check_func, cal_canshu_from_base_eq_ineq, check_inter
from mathsolver.functions.hanshu.hengchengli_leixing import (RenYiCunZaiXingDingYi, RenYiRenYiXingDingYi,
                                                             CunZaiCunZaiXingDingYi, CunZaiXingDingYi,
                                                             RenYiXingDingYi, CanBianFenLi)
from mathsolver.functions.hanshu.hengchengli_linjie import hengchengli_lingjie, XxXingDingYiZuiZhi
from mathsolver.functions.mathematica.mathematicaSolve import MathematicaSolve
from mathsolver.functions.sympy_utils import default_symbol


class HengChengLiXxXing(BaseFunction):
    """不等式恒成立问题：xx 型"""
    # 类型
    leixing = None
    fenli = True

    def solver(self, *args):
        # 第 2, 3 ... 个参数为 BaseBelong 类型
        transformed_args = [args[0]]
        for item in args[1:]:
            transformed_args.append(check_belong(item))

        args = transformed_args

        # 1. 参变分离
        if self.fenli:
            step_canbianfenli = CanBianFenLi().solver(*args)
            self.steps.extend(step_canbianfenli.steps)
            shuchu = step_canbianfenli.output
        else:
            shuchu = args

        # 2. “xx”型定义
        step_renyixing = self.leixing().solver(shuchu)
        self.steps.extend(step_renyixing.steps)

        # 3. 求最值
        step_zuizhi = XxXingDingYiZuiZhi(self.known).solver(step_renyixing.output)
        self.steps.extend(step_zuizhi.steps)

        # 4. 恒成立临界
        lingjie_output = hengchengli_lingjie(*step_zuizhi.output)

        # print lingjie_output

        # 求出参数符号
        canshu_symbol = cal_canshu_from_base_eq_ineq(args[0])

        # 5. 解不等式

        # 5.1 临界输出不含参数
        if not isinstance(lingjie_output[0], list):
            step_solve = self.jiebudengshi(BaseIneq(lingjie_output))
            self.steps.append(["", "根据临界条件得：%s" % BaseIneq(lingjie_output).printing()])
            self.steps.append(["", "所以最后参数取值范围为 %s" % step_solve])

            self.output.append(BaseSymbolValue({canshu_symbol: step_solve}))

        # 5.2 临界输出含参数
        else:
            res_collector = []
            for canshu_interval, ineq_value in lingjie_output:
                self.steps.append(["", "当 %s ∈ %s 时，满足条件 %s" %
                                   (canshu_symbol, latex(canshu_interval), BaseIneq(ineq_value).printing())])

                step_solve = self.jiebudengshi(BaseIneq(ineq_value))
                if step_solve:
                    res_collector.append(step_solve.intersect(canshu_interval))

            result = Union(res_collector)
            self.output.append(BaseSymbolValue({canshu_symbol: result}))
            self.steps.append(["", "所以最后 %s 的取值范围为 %s" % (canshu_symbol, latex(result))])
        self.label.add("恒成立问题")
        return self

    def jiebudengshi(self, ineq):
        """解不等式（特殊处理）：如果解集为无穷，则无解"""
        try:
            step_solve = JieBuDengShi().solver(ineq)
            # 特殊处理：如果解集为无穷，则无解
            for k, v in step_solve.output[0].value.items():
                key, val = k, v
            if val in (FiniteSet(oo), FiniteSet(-oo)):
                self.steps.append(["", "不等式无解"])
                step_solve.output = [BaseSymbolValue({key: EmptySet()})]
            else:
                self.steps.append(["", "解得 %s" % step_solve.output[0].printing()])
            return list(step_solve.output[0].value.values())[0]
        except Exception:
            # 如果出现 -oo >= 0 的情况，特殊处理
            res = solveset(' '.join([str(ele) for ele in ineq.value]), domain=S.Reals)
            if not res:
                self.steps.append(["", "不等式无解"])
            elif res == S.Reals:
                self.steps.append(["", "不等式恒成立"])
            else:
                raise ValueError("unknown inequality %s" % ' '.join([str(ele) for ele in ineq.value]))
            return res


class HengChengLiRenYiXing(HengChengLiXxXing):
    """不等式恒成立问题：任意型"""
    leixing = RenYiXingDingYi


class HengChengLiCunZaiXing(HengChengLiXxXing):
    """不等式恒成立问题：存在型"""
    leixing = CunZaiXingDingYi


class HengChengLiRenYiRenYiXing(HengChengLiXxXing):
    """不等式恒成立问题：“任意≥任意”型"""
    leixing = RenYiRenYiXingDingYi
    fenli = False


class HengChengLiCunZaiCunZaiXing(HengChengLiXxXing):
    """不等式恒成立问题：“存在≥存在”型"""
    leixing = CunZaiCunZaiXingDingYi
    fenli = False


class HengChengLiRenYiCunZaiXing(HengChengLiXxXing):
    """不等式恒成立问题：“任意≥（≤）存在”型"""
    leixing = RenYiCunZaiXingDingYi
    fenli = False


def fangcheng_hengchengli(eq):
    """hs014.方程恒成立得方程（组）"""

    expr = eq.lhs - eq.rhs
    symbol = default_symbol(expr)
    var_symbols = [symb for symb in expr.free_symbols if symb != symbol]

    # 带特殊值，解方程组
    eqs = []
    n = -1
    while n < len(var_symbols) + 1:
        eqs.append(expr.subs(symbol, n))
        n += 1
    eqs_mathematica = [[eq, 0] for eq in eqs]

    res_base_symbol_value = MathematicaSolve().solver(BaseIneqs(eqs_mathematica), BaseVariables(var_symbols)).output[0]
    res = res_base_symbol_value.value

    step = "由 %s = 0 恒成立解得 %s" % (latex(expr), res_base_symbol_value.printing())
    return res, step


class HengChengLiRenYiEqCunZai(BaseFunction):
    """“任意=存在”型：对任意 x1 ∈ A, 存在 x2 ∈ B， 使得 f(x1) = g(x2) 恒成立
    输入：f, g, x1, x2"""

    def solver(self, *args):
        f, g, f_inter, g_inter = check_func(args[0]), check_func(args[1]), check_inter(args[2]), check_inter(args[3])
        f_name, f_var, f_expr = f.name, f.var, f.expression
        g_name, g_var, g_expr = g.name, g.var, g.expression
        self.steps.append(["", "由题意知 %s(%s) 的值域是 %s(%s) 的值域的子集" % (f_name, f_var, g_name, g_var)])

        # 求 f, g 的值域
        from mathsolver.functions.hanshu.zhiyu import HanShuZhiYu
        f_zhiyu_solver = HanShuZhiYu(self.known).solver(f, f_inter)
        g_zhiyu_solver = HanShuZhiYu(self.known).solver(g, g_inter)
        self.steps.extend(f_zhiyu_solver.steps)
        self.steps.extend(g_zhiyu_solver.steps)
        f_zhiyu = f_zhiyu_solver.output[0].value
        g_zhiyu = g_zhiyu_solver.output[0].value

        # 集合关系求参数
        from mathsolver.functions.jihe.jihe_solve import jihe_solve
        result = jihe_solve()._solve_child_unival(f_zhiyu, g_zhiyu)
        canshu = (f_expr.free_symbols.union(g_expr.free_symbols) - {f_var}).pop()
        output_result = BaseSymbolValue({canshu: result})

        self.steps.append(["", "解得 %s" % output_result.printing()])
        self.output.append(output_result)
        self.label.add("恒成立问题 - 任意=存在”型")
        return self


if __name__ == '__main__':
    pass
